package Controls;

import App.DCCanvas;
import Forms.Output;
import old_Core.AlternateCore;
import MathCore.CircularArray;
import Core.Control;
import Core.GM;
import Core.GUICanvas;
import MathCore.Real;
import old_Core.SolveException;
import old_Core.SortException;
import java.util.Vector;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

public class old_Plotter extends Control
{
	private Vector rpnFunctions = new Vector();
	private Vector rpnNames = new Vector();
	private CircularArray points[][];

	public Real sx = new Real(0),  sy = new Real(0),  scale = new Real(16);
	public Real cx = new Real(0),  cy = new Real(0);
	private Real tmp1 = new Real(0),  tmp2 = new Real(0),  tmp3 = new Real(0);
	
	public boolean modified = true;
	public boolean syModified = true;
	public boolean sxModified = true;
	public boolean scaleModified = true;

	public boolean showLegend = true;

	private static int bgcolor = 0xffffff;
	private int colorPallete[] = {0x990030, 0xed1c24, 0xff7e00, 0xffc20e, 0xa8e61d, 0x22b14c, 0x00b7ef, 0x2f3699, 0x6f3198};

	public old_Plotter(Vector functions, int w, int h)
	{
		super(w, h);
		prepareToPlot(functions);

		cx.assign(w / 2);
		cy.assign(h / 2);
	}

	private void prepareToPlot(Vector functions)
	{
		/*
		points = new CircularArray[functions.size()][2];
		
		ElementBox func;

		DCCanvas.activeCore = new AlternateCore();

		for (int i = 0; i < functions.size(); i++)
		{
			points[i][0] = new CircularArray(getW());
			points[i][1] = new CircularArray(getW());

			func = (ElementBox) functions.elementAt(i);

			Vector rpn = null;

			try
			{
				rpn = DCCanvas.activeCore.normalToRPN(func.elements);
			}
			catch (SortException e)
			{
				System.out.println(e.getMessage());

				Output out = new Output();
				out.addText(func.staticText+e.getMessage());

				return;
			}

			rpnFunctions.addElement(rpn);
			rpnNames.addElement(func.staticText);
		}
		 *
		 *
		 */
	}

	public Real toGlobalX(Real local)
	{
		if (local.isNan())
		{
			return local;
		}

		local.add(sx);
		local.mul(scale);
		local.add(cx);
		return local;
	}

	public Real toGlobalY(Real local)
	{
		if (local.isNan())
		{
			return local;
		}

		local.add(sy);
		local.mul(scale);
		local.mul(-1);
		local.add(cy);
		return local;
	}

	public Real toLocalY(Real global)
	{
		global.sub(cy);
		global.mul(-1);
		global.div(scale);
		global.sub(sy);
		return global;
	}

	public Real toLocalX(Real global)
	{
		global.sub(cx);
		global.div(scale);
		global.sub(sx);
		return global;
	}

	public void drawHorAxe(int y, Graphics g)
	{
		Real ry = new Real(y);
		ry.assign(toGlobalY(ry));

		if (ry.toInteger() < 0 || ry.toInteger() > getH())
		{
			return;
		}

		g.drawLine(0, ry.toInteger(), getW(), ry.toInteger());
	}

	public void drawVertAxe(int x, Graphics g)
	{
		Real rx = new Real(x);
		rx.assign(toGlobalX(rx));

		if (rx.toInteger() < 0 || rx.toInteger() > getW())
		{
			return;
		}

		g.drawLine(rx.toInteger(), 0, rx.toInteger(), getH());
	}

	public void draw(Graphics g, int x, int y)
	{
		//long timestart = System.currentTimeMillis();

		//ElementBox graph;
		Vector rpn = new Vector();

		g.setClip(x, y, x+getW(), y+getH());

		DCCanvas.activeCore.reset();

		g.setColor(bgcolor); // заполнить фон
		g.fillRect(x, y, getW(), getH());

		if (scale.greaterEqual(4))
		{
			// comment 

			g.setColor(0xaaaaaa);  // вспомогательные оси серого цвета

			Real top = toLocalY(new Real(0));
			Real bottom = toLocalY(new Real(getH()));
			Real left = toLocalX(new Real(0));
			Real right = toLocalX(new Real(getW()));

			for (int i = bottom.toInteger(); i <= top.toInteger(); i++)
			{
				drawHorAxe(i, g);
			}
			for (int i = left.toInteger(); i <= right.toInteger(); i++)
			{
				drawVertAxe(i, g);
			}

			if (scale.greaterEqual(16))
			{
				g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM));

				Real tx = new Real(), ty = new Real();

				ty.assign(0);
				toGlobalY(ty);
				for (int i = left.toInteger(); i <= right.toInteger(); i++)
				{
					tx.assign(i);
					toGlobalX(tx);
					g.drawString("" + i, tx.toInteger(), ty.toInteger(), Graphics.TOP | Graphics.RIGHT);
				}

				tx.assign(0);
				toGlobalX(tx);
				for (int i = bottom.toInteger(); i <= top.toInteger(); i++)
				{
					ty.assign(i);
					toGlobalY(ty);
					g.drawString("" + i, tx.toInteger(), ty.toInteger(), Graphics.TOP | Graphics.RIGHT);
				}
			}
		}

		g.setColor(0);  // основные оси черного цвета
		drawHorAxe(0, g);
		drawVertAxe(0, g);

		Real tmp3 = new Real(0), tmp4 = new Real(0);

		for (int i = 0; i < rpnFunctions.size(); i++)
		{
			g.setColor(0);

			rpn = (Vector) rpnFunctions.elementAt(i);

			Real dscale = new Real(1);
			dscale.div(scale);

			if (scaleModified || sxModified || syModified) // просчитать точки снова
			{
				for (tmp1.assign(toLocalX(tmp2.assign(0))); tmp1.lessThan(toLocalX(tmp2.assign(getW()))); tmp1.add(dscale))
				{
					DCCanvas.activeCore.x_var.assign(tmp1);

					try
					{
						tmp2.assign(DCCanvas.activeCore.solve(rpn).r);
					} catch (SolveException e)
					{
						System.out.println(e.getMessage());

						Output out = new Output();
						out.addText(((String)rpnNames.elementAt(i)) + e.getMessage());
						
						break;
					}

					tmp3.assign(tmp1);
					tmp4.assign(tmp2);

					points[i][0].addToEnd(toGlobalX(tmp3));
					points[i][1].addToEnd(toGlobalY(tmp4));
				}
			}

			g.setColor(colorPallete[i%colorPallete.length]);

			for (int j = 0; j < points[i][0].lenght() - 1; j++)
			{
				if (!points[i][0].get(j).isNan() && !points[i][1].get(j).isNan() && !points[i][0].get(j + 1).isNan() && !points[i][1].get(j + 1).isNan())
				{
					g.drawLine(points[i][0].get(j).toInteger(), points[i][1].get(j).toInteger(), points[i][0].get(j + 1).toInteger(), points[i][1].get(j + 1).toInteger());
				}
			}
		}
		
		if(showLegend)
		{
			Font lfont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
			g.setFont(lfont);

			g.setColor(bgcolor);
			g.fillRect(2, 2, lfont.stringWidth("a "), lfont.getHeight()*rpnNames.size()+4);
			g.setColor(0);
			g.drawRect(2, 2, lfont.stringWidth("a "), lfont.getHeight()*rpnNames.size()+4);
			
			for(int i=0; i<rpnNames.size(); i++)
			{
				g.setColor(colorPallete[i%colorPallete.length]);
				g.drawString(((String)rpnNames.elementAt(i)).substring(0, 1), 4, 4+i*g.getFont().getHeight(), Graphics.LEFT | Graphics.TOP);
			}

			g.setFont(Font.getDefaultFont());
		}

		sxModified = false;
		syModified = false;
		scaleModified = false;

		//System.out.println("redraw: "+(System.currentTimeMillis() - timestart) + "ms");
	}

	public void onEvent(int event, Object param)
	{
		super.onEvent(event, param);

		switch(event)
		{
			case GM.UPPER_FORM_CLOSED:
				//if(param instanceof OutputForm) parentForm.close();
		}
	}

}
